package com.shuiyun.jtt.controller;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.codec.BCD;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.io.IoUtil;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.RandomUtil;
import cn.hutool.core.util.ZipUtil;
import com.alibaba.fastjson.JSON;
import com.shuiyun.jtt.entity.bo.CommandMileage;
import com.shuiyun.jtt.entity.bo.CommandPulseFactor;
import com.shuiyun.jtt.entity.bo.CommandStatus;
import com.shuiyun.jtt.entity.bo.CommandVehicleInfo;
import com.shuiyun.jtt.entity.form.*;
import com.shuiyun.jtt.enums.JT808;
import com.shuiyun.jtt.message.Header;
import com.shuiyun.jtt.message.JTMessage;
import com.shuiyun.jtt.message.jt808.*;
import com.shuiyun.jtt.message.jt808.extend.IntegerId;
import com.shuiyun.jtt.session.Session;
import com.shuiyun.jtt.session.SessionManager;
import com.shuiyun.jtt.utils.ByteUtil;
import com.shuiyun.jtt.utils.IdUtil;
import com.shuiyun.jtt.utils.TachographUtil;
import com.shuiyun.jtt.utils.ValidatorUtil;
import com.shuiyun.jtt.utils.codec.CoderDecoderUtil;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayOutputStream;
import java.io.InputStream;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @author shuiyun
 * @description 测试接口
 * @date 2022-04-16 16:53
 */
@Slf4j
@Api(tags = "测试接口")
@RestController
@RequestMapping("test")
public class TestController {

    @Autowired
    private SessionManager sessionManager;

    private final AtomicInteger serialNo = new AtomicInteger(0);


    @GetMapping
    @ApiOperation("测试接口")
    public String test(){
        return "shuiyun";
    }

    @GetMapping("/location")
    @ApiOperation("获取设备实时定位")
    public String location(String client){
        Session session = sessionManager.get(client);
        JTMessage message = new JTMessage();
        message.setHeader(new Header(JT808.位置信息查询0x8201,serialNo.getAndIncrement(),client));
        session.getChannel().writeAndFlush(message);
        return "ok"+ DateUtil.now();
    }

    @PostMapping("/t8103")
    @ApiOperation("设置终端参数")
    public String t8103(@RequestBody T8103Form form){
        Session session = getSession(form);
        T8103 t8103 = new T8103();
        t8103.setTerminalParam(form.getParams());
        t8103.setHeader(JT808.设置终端参数0x8103,form.getClientId(),serialNo.getAndIncrement());
        session.getChannel().writeAndFlush(t8103);
        return "ok"+ DateUtil.now();
    }

    @PostMapping("/t8106")
    @ApiOperation("查询指定终端参数")
    public String t8106(@RequestBody T8106Form form){
        Session session = getSession(form);
        List<IntegerId> ids = IdUtil.getIntegerId(form.getIds());
        T8106 t8106 = new T8106(ids);
        t8106.setHeader(JT808.查询指定终端参数0x8106,form.getClientId(),serialNo.getAndIncrement());
        session.getChannel().writeAndFlush(t8106);
        return "ok"+ DateUtil.now();
    }

    @PutMapping("/t8108")
    @ApiOperation("下发终端升级包")
    public String t8108(T8108Form form,@RequestParam("file") MultipartFile file){
        Session session = getSession(form);
        T8108 t8108 = BeanUtil.copyProperties(form, T8108.class);
        try (InputStream inputStream = file.getInputStream();
                ByteArrayOutputStream outputStream = new ByteArrayOutputStream();){
            IoUtil.copy(inputStream, outputStream);
            byte[] bytes = outputStream.toByteArray();
            t8108.setPacket(bytes);
        }catch (Exception e){
            return "error"+e.getMessage();
        }
        t8108.setHeader(JT808.下发终端升级包0x8108,form.getClientId(),serialNo.getAndIncrement());
        session.getChannel().writeAndFlush(t8108);
        return "ok"+ DateUtil.now();
    }

    @PostMapping("/t8202")
    @ApiOperation("设备定时回传定位")
    public String t8202(@RequestBody T8202Form form){
        Session session = getSession(form);
        T8202 t8202 = BeanUtil.copyProperties(form,T8202.class);
        t8202.setHeader(new Header(JT808.临时位置跟踪控制0x8202,serialNo.getAndIncrement(),form.getClientId()));
        session.getChannel().writeAndFlush(t8202);
        return "ok"+ DateUtil.now();
    }

    @PostMapping("/t8203")
    @ApiOperation("人工确认报警消息")
    public String t8203(@RequestBody T8203Form form){
        Session session = getSession(form);
        T8203 t8203 = BeanUtil.copyProperties(form,T8203.class);
        t8203.setHeader(new Header(JT808.人工确认报警消息0x8203,serialNo.getAndIncrement(),form.getClientId()));
        session.getChannel().writeAndFlush(t8203);
        return "ok"+ DateUtil.now();
    }

    @PostMapping("/common")
    @ApiOperation("通用指令下发")
    public String common(@RequestBody CommonForm form){
        Session session = getSession(form);
        JTMessage message = new JTMessage();
        // 去除0x
        form.setMessageId(form.getMessageId().replaceAll("0x",""));
        message.setHeader(new Header(Integer.parseInt(form.getMessageId(),16),serialNo.getAndIncrement(),form.getClientId()));
        session.getChannel().writeAndFlush(message);
        return "ok"+ DateUtil.now();
    }


    @PostMapping("/t8300")
    @ApiOperation("文本消息下发")
    public String t8300(@RequestBody T8300Form form){
        Session session = getSession(form);
        T8300 t8300 = BeanUtil.copyProperties(form, T8300.class);
        t8300.setHeader(new Header(JT808.文本信息下发0x8300,serialNo.getAndIncrement(),form.getClientId()));
        session.getChannel().writeAndFlush(t8300);
        return "ok"+ DateUtil.now();
    }

    @PostMapping("/t8400")
    @ApiOperation("电话回拨")
    public String t8400(@RequestBody T8400Form form){
        Session session = getSession(form);
        T8400 t8400 = BeanUtil.copyProperties(form, T8400.class);
        t8400.setHeader(new Header(JT808.电话回拨0x8400,serialNo.getAndIncrement(),form.getClientId()));
        session.getChannel().writeAndFlush(t8400);
        return "ok"+ DateUtil.now();
    }

    @PostMapping("/t8401")
    @ApiOperation("设置电话本")
    public String t8401(@RequestBody T8401Form form){
        Session session = getSession(form);
        T8401 t8401 = BeanUtil.copyProperties(form, T8401.class);
        t8401.setHeader(new Header(JT808.设置电话本0x8401,serialNo.getAndIncrement(),form.getClientId()));
        session.getChannel().writeAndFlush(t8401);
        return "ok"+ DateUtil.now();
    }

    @PostMapping("/t8500")
    @ApiOperation("车辆参数控制")
    public String t8500(@RequestBody T8500Form form){
        Session session = getSession(form);
        Map<Integer, Object> parameter = form.getParameter();
        T8500 t8500 = new T8500();
        t8500.setParameter(parameter);
        t8500.setHeader(new Header(JT808.车辆控制0x8500,serialNo.getAndIncrement(),form.getClientId()));
        session.getChannel().writeAndFlush(t8500);
        return "ok"+ DateUtil.now();
    }

    @PostMapping("/t8600")
    @ApiOperation("设置圆形区域")
    public String t8600(@RequestBody T8600Form form){
        Session session = getSession(form);
        T8600 t8600 = BeanUtil.copyProperties(form, T8600.class);
        t8600.setHeader(new Header(JT808.设置圆形区域0x8600,serialNo.getAndIncrement(),form.getClientId()));
        session.getChannel().writeAndFlush(t8600);
        return "ok"+ DateUtil.now();
    }

    @PostMapping("/t8601")
    @ApiOperation("删除圆形区域")
    public String t8601(@RequestBody DelAreaForm form){
        Session session = getSession(form);
        T8601 t8601 = getT8601(form);
        t8601.setHeader(new Header(JT808.删除圆形区域0x8601,serialNo.getAndIncrement(),form.getClientId()));
        session.getChannel().writeAndFlush(t8601);
        return "ok"+ DateUtil.now();
    }

    @PostMapping("/t8602")
    @ApiOperation("设置矩形区域")
    public String t8602(@RequestBody T8602Form form){
        Session session = getSession(form);
        T8602 t8602 = BeanUtil.copyProperties(form, T8602.class);
        t8602.setHeader(new Header(JT808.设置矩形区域0x8602,serialNo.getAndIncrement(),form.getClientId()));
        session.getChannel().writeAndFlush(t8602);
        return "ok"+ DateUtil.now();
    }

    @PostMapping("/t8603")
    @ApiOperation("删除矩形区域")
    public String t8603(@RequestBody DelAreaForm form){
        Session session = getSession(form);
        T8601 t8601 = getT8601(form);
        t8601.setHeader(new Header(JT808.删除矩形区域0x8603,serialNo.getAndIncrement(),form.getClientId()));
        session.getChannel().writeAndFlush(t8601);
        return "ok"+ DateUtil.now();
    }

    @PostMapping("/t8604")
    @ApiOperation("设置多边形区域")
    public String t8604(@RequestBody T8604Form form){
        Session session = getSession(form);
        T8604 t8604 = BeanUtil.copyProperties(form, T8604.class);
        t8604.setHeader(new Header(JT808.设置多边形区域0x8604,serialNo.getAndIncrement(),form.getClientId()));
        session.getChannel().writeAndFlush(t8604);
        return "ok"+ DateUtil.now();
    }

    @PostMapping("/t8605")
    @ApiOperation("删除多边形区域")
    public String t8605(@RequestBody DelAreaForm form){
        Session session = getSession(form);
        T8601 t8601 = getT8601(form);
        t8601.setHeader(new Header(JT808.删除多边形区域0x8605,serialNo.getAndIncrement(),form.getClientId()));
        session.getChannel().writeAndFlush(t8601);
        return "ok"+ DateUtil.now();
    }

    @PostMapping("/t8606")
    @ApiOperation("设置路线区域")
    public String t8606(@RequestBody T8606Form form){
        Session session = getSession(form);
        T8606 t8606 = BeanUtil.copyProperties(form, T8606.class);
        t8606.setHeader(new Header(JT808.设置路线0x8606,serialNo.getAndIncrement(),form.getClientId()));
        session.getChannel().writeAndFlush(t8606);
        return "ok"+ DateUtil.now();
    }

    @PostMapping("/t8607")
    @ApiOperation("删除路线区域")
    public String t8607(@RequestBody DelAreaForm form){
        Session session = getSession(form);
        T8601 t8601 = getT8601(form);
        t8601.setHeader(new Header(JT808.删除路线0x8607,serialNo.getAndIncrement(),form.getClientId()));
        session.getChannel().writeAndFlush(t8601);
        return "ok"+ DateUtil.now();
    }

    @PostMapping("/t8608")
    @ApiOperation("区域查询")
    public String t8608(@RequestBody T8608Form form){
        Session session = getSession(form);
        T8608 t8608 = new T8608(form.getType(),IdUtil.getIntegerId(form.getIds()));
        t8608.setHeader(new Header(JT808.查询区域或线路数据0x8608,serialNo.getAndIncrement(),form.getClientId()));
        session.getChannel().writeAndFlush(t8608);
        return "ok"+ DateUtil.now();
    }

    @PostMapping("/t8700")
    @ApiOperation("行驶记录仪数据采集命令")
    public String t8700(@RequestBody T8700Form form){
        if (ObjectUtil.isNull(form.getCommand())){
            throw new RuntimeException("命令字不能为空");
        }
        // 命令字大于7的命令需要校验开始时间 结束时间 个数字段
        Session session = getSession(form);
        T8700 t8700 = null;
        if (form.getCommand() > 7){
            ValidatorUtil.validate(form);
            ByteBuf buf = CoderDecoderUtil.obj2ByteBuf(form);
            t8700 = new T8700(form.getCommand(), TachographUtil.encode(form.getCommand().byteValue(), ByteUtil.readReadableBytes(buf)));
        }else{
            t8700 = new T8700(form.getCommand(), TachographUtil.encode(form.getCommand().byteValue(),new byte[0]));
        }
        t8700.setHeader(JT808.行驶记录仪数据采集命令0x8700,form.getClientId(),serialNo.getAndIncrement());
        session.getChannel().writeAndFlush(t8700);
        return "ok"+ DateUtil.now();
    }

    @PostMapping("/t8701")
    @ApiOperation("设置行驶记录仪数据")
    public String t8701(@RequestBody T8701Form form){
        if (ObjectUtil.isNull(form.getCommand())){
            throw new RuntimeException("命令字不能为空");
        }
        Session session = getSession(form);
        byte[] bytes = null;
        switch (form.getCommand()){
            case 0x82:
                CommandVehicleInfo commandVehicleInfo = BeanUtil.copyProperties(form, CommandVehicleInfo.class);
                ByteBuf buf1 = CoderDecoderUtil.obj2ByteBuf(commandVehicleInfo);
                bytes = ByteUtil.readReadableBytes(buf1);
                break;
            case 0x83:
                String installTime = DateUtil.format(form.getInstallTime(), "yyMMddHHmmss");
                bytes = BCD.strToBcd(installTime);
                break;
            case 0x84:
                CommandStatus commandStatus = BeanUtil.copyProperties(form, CommandStatus.class);
                ByteBuf buf2 = CoderDecoderUtil.obj2ByteBuf(commandStatus);
                bytes = ByteUtil.readReadableBytes(buf2);
                break;
            case 0xc2:
                String realTime = DateUtil.format(new Date(), "yyMMddHHmmss");
                bytes = BCD.strToBcd(realTime);
                break;
            case 0xc3:
                CommandPulseFactor pulseFactor = new CommandPulseFactor(new Date(),form.getPulseFactor());
                ByteBuf buf3 = CoderDecoderUtil.obj2ByteBuf(pulseFactor);
                bytes = ByteUtil.readReadableBytes(buf3);
                break;
            case 0xc4:
                CommandMileage mileage = BeanUtil.copyProperties(form, CommandMileage.class);
                ByteBuf buf4 = CoderDecoderUtil.obj2ByteBuf(mileage);
                bytes = ByteUtil.readReadableBytes(buf4);
                break;
            default:
                break;
        }
        if (ObjectUtil.isNull(bytes)){
            throw new RuntimeException("未识别或处理异常的指令："+form.getCommand());
        }
        byte[] encode = TachographUtil.encode(form.getCommand().byteValue(), bytes);
        T8700 t8701 = new T8700(form.getCommand(),encode);
        t8701.setHeader(JT808.行驶记录仪参数下传命令0x8701,form.getClientId(),serialNo.getAndIncrement());
        session.getChannel().writeAndFlush(t8701);
        return "ok"+ DateUtil.now();
    }



    @PostMapping("/t8801")
    @ApiOperation("摄像头立即拍摄")
    public String t8801(@RequestBody T8801Form form){
        Session session = getSession(form);
        T8801 t8801 = BeanUtil.copyProperties(form, T8801.class);
        t8801.setHeader(JT808.摄像头立即拍摄命令0x8801,form.getClientId(),serialNo.getAndIncrement());
        session.getChannel().writeAndFlush(t8801);
        return "ok"+ DateUtil.now();
    }

    @PostMapping("/t8802")
    @ApiOperation("存储多媒体数据检索")
    public String t8802(@RequestBody T8802Form form){
        Session session = getSession(form);
        T8802 t8802 = BeanUtil.copyProperties(form, T8802.class);
        t8802.setHeader(JT808.存储多媒体数据检索0x8802,form.getClientId(),serialNo.getAndIncrement());
        session.getChannel().writeAndFlush(t8802);
        return "ok"+ DateUtil.now();
    }

    @PostMapping("/t8803")
    @ApiOperation("存储多媒体数据上传")
    public String t8803(@RequestBody T8803Form form){
        Session session = getSession(form);
        T8803 t8803 = BeanUtil.copyProperties(form, T8803.class);
        t8803.setHeader(JT808.存储多媒体数据上传0x8803,form.getClientId(),serialNo.getAndIncrement());
        session.getChannel().writeAndFlush(t8803);
        return "ok"+ DateUtil.now();
    }

    @PostMapping("/t8804")
    @ApiOperation("录音开始命令")
    public String t8804(@RequestBody T8804Form form){
        Session session = getSession(form);
        T8804 t8804 = BeanUtil.copyProperties(form, T8804.class);
        t8804.setHeader(JT808.录音开始命令0x8804,form.getClientId(),serialNo.getAndIncrement());
        session.getChannel().writeAndFlush(t8804);
        return "ok"+ DateUtil.now();
    }

    @PostMapping("/t0900")
    @ApiOperation("消息透传下行")
    public String t0900(@RequestBody T0900Form form){
        Session session = getSession(form);
        T0900 t0900 = BeanUtil.copyProperties(form, T0900.class);
        t0900.setHeader(JT808.数据下行透传0x8900,form.getClientId(),serialNo.getAndIncrement());
        session.getChannel().writeAndFlush(t0900);
        return "ok"+ DateUtil.now();
    }

    @PostMapping("/t0a00")
    @ApiOperation("平台RAS秘钥")
    public String t0a00(@RequestBody BaseForm form){
        Session session = getSession(form);
        T0A00 t0A00 = new T0A00(RandomUtil.randomInt(141436958),RandomUtil.randomBytes(128));
        t0A00.setHeader(JT808.平台RSA公钥0x8A00,form.getClientId(),serialNo.getAndIncrement());
        session.getChannel().writeAndFlush(t0A00);
        return "ok"+ DateUtil.now();
    }



    ///////////////////////////////// 以下为私有方法  ///////////////////////////////////////////

    /**
     * 拼装删除区域基本信息
     * @param form 需要被删除的数据
     * @return 即将发送的数据实体
     */
    private T8601 getT8601(@RequestBody DelAreaForm form) {
        if (CollectionUtil.isEmpty(form.getIds())) {
            throw new RuntimeException("无需要删除的id 无效命令不予执行");
        }
        List<IntegerId> ids = IdUtil.getIntegerId(form.getIds());
        T8601 t8601 = new T8601();
        t8601.setIds(ids);
        return t8601;
    }


    /**
     * 私有方法 根据客户端卡号好货session信息
     * @param form
     * @return
     */
    private Session getSession(BaseForm form){
        Session session = sessionManager.get(form.getClientId());
        if (ObjectUtil.isNull(session)){
            throw new RuntimeException("无当前卡号设备在线，卡号："+form.getClientId());
        }
        return session;
    }
}
